<?php
class CDb
{
	const PARAM_INT = PDO::PARAM_INT;
	const PARAM_STR = PDO::PARAM_STR;
	const PARAM_BOOl = PDO::PARAM_BOOL;

	const FETCH_OBJ = PDO::FETCH_OBJ;
	const FETCH_ASSOC = PDO::FETCH_ASSOC;
	const FETCH_NUM = PDO::FETCH_NUM;

	private $_conn;

	public function init()
	{
		$this->_conn = new PDO(C::app()->config['db']['connection'],
			C::app()->config['db']['user'], C::app()->config['db']['pass']);

		$this->_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	}

	public function addPrefix($sql)
	{
		return preg_replace_callback('/({{[\w\d]+}})/', create_function(
			'$matches',
			'return C::app()->config["db"]["prefix"].mb_substr($matches[1], 2, mb_strlen($matches[1], "UTF-8") - 4, "UTF-8");'
		), $sql);
	}

	public function command($sql)
	{
		$sql = $this->addPrefix($sql);
		return new CDbCommand($this->_conn->prepare($sql));
	}

	public function transaction()
	{
		if ($this->_conn)
			return $this->_conn->beginTransaction();
		return false;
	}

	public function rollBack()
	{
		if ($this->_conn)
			return $this->_conn->rollBack();
	}

	public function commit()
	{
		if ($this->_conn)
			return $this->_conn->commit();
	}

	public function close()
	{
		if ($this->_conn)
			$this->_conn = null;
	}
}

class CDbCommand
{
	private $_stat;

	public function __construct($statement)
	{
		$this->_stat = $statement;
	}

	public function execute($params = array())
	{
		$this-> $this->_stat->exectute($params);
	}

	public function bindParam($param, $value, $type)
	{
		if ($this->_stat)
			$this->_stat->bindParam($param, $value, $type);
	}

	public function bindValue($param, $value, $type)
	{
		if ($this->_stat)
			$this->_stat->bindValue($param, $value, $type);
	}

	public function fetch($type = CDb::FETCH_OBJ)
	{
		if ($this->_stat)
			return $this->_stat->fetch($type);
	}

	public function fetchAll($type = CDb::FETCH_OBJ)
	{
		$result = array();

		if ($this->_stat)
		{
			while ($row = $this->_stat->fetch($type))
				$result[] = $row;
		}

		return $result;
	}

	public function fetchColumn()
	{
		if ($this->_stat)
			return $this->_stat->fetchColumn();
	}

	public function affectedRows()
	{
		if ($this->_stat)
			return $this->_stat->rowCount();
	}
}